#include "Cache.hpp"

#include <iostream>
#include <string>
#include <unordered_map>
#include <sstream>
#include <fstream>
#include <list>
using std::ifstream;
using std::ofstream;
using std::endl;
using std::cout;
using std::cerr;
using std::istringstream;
using std::list;
using std::make_pair;

namespace ylw
{

Cache::Cache(int num)
: _name(num)
{    
}

//拷贝构造函数
//只把cache过去，复制无序map
Cache::Cache(const Cache & cache)
{
   auto it1 = cache._hashMap.begin();
   auto it2 = cache._hashMap.end();
   for(; it1 != it2; ++it1){
       _hashMap.insert(make_pair(it1->first, it1->second));
   }
}


//如果缓存里查找不到，数据会去词典中查找，之后会把结果存储到
//缓存中，那么只需添加内容到缓存中，同时把数据插到_updateData头部
void Cache::addElement(const string &key, const string &value){
    auto it = _hashMap.find(key);
    if(it != _hashMap.end()){
        cout << key << " exits here! addElement failed" << endl; 
    }else{
        _hashMap.insert(make_pair(key, value));//添加到缓存中
        _updateData.insert(_updateData.begin(), make_pair(key, value));
        _data.insert(make_pair(key, _updateData.begin()));//更新list，记录插入数据在list中的位置

        cout << "new pair added :";
        cout <<  _data[key]->first << " " << _data[key]->second << endl;
    }
}

// 查询操作，如果用户关键词在缓存中找不到，去索引查
// 如果在缓存中找到该关键词，那么返回结果，并更新冷热数据
string Cache::query(string &key){
    auto it = _hashMap.find(key);
    if(it != _hashMap.end()){
        auto it2 = _data.find(key);
        if(it2 != _data.end()){
            _updateData.erase(it2->second);
            _updateData.insert(_updateData.begin(), make_pair(key, it->second));
            _data.erase(it2);
            /* _data[key] = _updateData.begin(); */
            _data.insert(make_pair(key, _updateData.begin()));
        }
        cout << it->first << " has been found in Cache" << endl;
        cout << "query result is:" << it->second << endl;
        return it->second;
    }else{
        cout << "keyword:" << key << " is not in here" << endl;
        return string();
    }
} 

// 从磁盘文件读取缓存文件到内存中
void Cache::readFromFile(const string &filename){
    ifstream ifs(filename.c_str());
    if(!ifs){
        cerr << "ifs open file error" << endl;
    }

    string line;
    string keyword, value;
    while(getline(ifs, line)){
        istringstream iss(line);
        iss >> keyword >> value;
        _hashMap.insert(make_pair(keyword, value));
    }
    ifs.close();
}

// 把缓存写回到文件中保存
void Cache::writeToFile(const string &filename){
    ofstream ofs(filename.c_str());
    if(!ofs){
        cerr << "ofs open file error" << endl;
    }
    
    for(auto it = _hashMap.begin(); it != _hashMap.end(); ++it){
        ofs << it->first << " " <<  it->second << endl; 
    }
    ofs.close();
}

// 定时更新每个缓存中的内容，把全局cache的内容复制到当前缓存
void Cache::update(const Cache &rhs){
    auto it1 = rhs._hashMap.begin();
    auto it2 = rhs._hashMap.end();

    for(; it1 != it2; ++it1){
        _hashMap[it1->first] =  it1->second;
    }
}

}//end of namespace ylw
